Skip to content

docs: extend IR to the full cross-format capability surface - #3

Merged
OmarAlJarrah merged 2 commits into
mainfrom
docs/ir-full-capability-surface
Jul 19, 2026
Merged

docs: extend IR to the full cross-format capability surface#3
OmarAlJarrah merged 2 commits into
mainfrom
docs/ir-full-capability-surface

Conversation

@OmarAlJarrah

Copy link
Copy Markdown
Member

Summary

The IR draft had gaps that would have forced schema changes the moment later frontends landed — violating the core rule that only frontends are staged over time while the IR capability surface is complete from day one. This revision closes them, based on an audit of the model against the official specs for Smithy 2.0, TypeSpec (language + http/streams/SSE/events/versioning/rest/xml libraries and the current visibility system), Protobuf (proto2/proto3/editions, gRPC + transcoding), GraphQL (October 2021 + working draft), AsyncAPI 3.0, and OpenAPI 3.1/3.2, plus a representability sweep over Thrift, Avro, JSON-RPC/OpenRPC, WSDL, and Cap'n Proto. It also adds Erlang/OTP as a supported frontend target, scoped to the message-protocol surface (gen_server/gen_statem/gen_event call/cast/info, Dialyzer type language).

Headline changes to docs/ir-design.md (normative):

  • One-way operationsOperation.OneWay distinguishes fire-and-forget (OTP cast, AsyncAPI send-without-reply, Thrift oneway, JSON-RPC notifications) from "response with no body".
  • Messages get identityMessageID + Document.Messages registry (they were embedded by value, contradicting the no-embedded-named-nodes rule, and MessageRef was referenced but never defined); AsyncAPI request-reply gains Reply with static channel + dynamic reply address + reply message set; message headers become a typed schema.
  • Erlang/OTP support — new OTPBinding (behaviour, call/cast/info, target process as a channel, request tag); positional discrimination (Discriminator.Index) for tagged-tuple unions; Model.Positional for records; symbol values for atoms.
  • Services gain IDs, inheritance (Extends), per-service versions/renames, and protocol declarations; servers gain names, server-scoped auth (AsyncAPI's primary placement), and protocol versions.
  • OpBindings.HTTP becomes a slice — gRPC transcoding additional_bindings needs N HTTP mappings per operation; bindings also gain transcoding path patterns, response_body projection, compression/checksum obligations, and shared routes.
  • Property gains Presence (protobuf implicit/explicit/required — not nullability), ClientOptional/DefaultAdded (Smithy evolution model), EventPayload; WireID becomes *int (0 is a legal ordinal in Cap'n Proto/FlatBuffers/Avro).
  • Visibility.None (@invisible), operation-level visibility overrides, type-level XML/wire-name/media-type hints, richer Example (input↔output/error scenarios, header+payload pairs), Availability on enum members/variants/parameters with add/remove cycles and optionality flips.
  • AuthKind covers the SASL/X509/userPassword families; Extensions/Provenance now exist on every node that can carry source metadata (responses, contents, examples, flows, bindings, auth schemes).
  • Documented conventions for degraded constructs (§4.8): TypeSpec never/string templates, Erlang bit-sized binaries and funs, Smithy waiters and endpoint rules, GraphQL directive ordering and @oneOf lowering.

docs/ir-spec-matrix.md gains the Erlang/OTP column, six new capability rows (one-way ops, positional encoding, symbol literals, unsolicited messages, multi-format payload schemas, extension ranges), and ~25 cell corrections (e.g. Smithy optionality-vs-nullability was overstated, protobuf reserved is not versioning, GraphQL has no server construct). architecture.md and CLAUDE.md add OTP to the format lists.

Test plan

  • Docs-only change; no code exists yet (design stage).
  • Verified internal consistency: every struct/field referenced by the lowering summaries (§14) and matrix exists in the model; no references to removed shapes (MessageRef, ReplyTo, FilenameParam, bool XML node flags) remain.
  • When Milestone 1 lands, the capability-conformance corpus (one minimal spec per matrix row per format) is the executable check for these claims.

The IR draft could not losslessly host several constructs that the target
source formats declare, which would have forced schema changes the moment
those frontends landed. Close the gaps found by auditing the model against
Smithy 2.0, TypeSpec (incl. http/streams/sse/events/versioning/rest/xml and
the new visibility system), Protobuf (proto2/proto3/editions + gRPC
transcoding), GraphQL (current spec + draft), AsyncAPI 3.0, OpenAPI 3.1/3.2,
and a sweep of Thrift/Avro/JSON-RPC/WSDL/Cap'n Proto — and add Erlang/OTP
(gen_server/gen_statem/gen_event message-protocol surface) as a supported
frontend target.

Headline model changes:
- Operation.OneWay: fire-and-forget ops (OTP cast, AsyncAPI send-without-
  reply, Thrift oneway, JSON-RPC notifications) are distinct from
  "response with no body"
- messages become registry citizens (MessageID, Document.Messages);
  AsyncAPI request-reply gains Reply with dynamic reply addresses
- new OTPBinding (call/cast/info against a process channel); positional
  discrimination (Discriminator.Index) and Model.Positional for tagged
  tuples and records; symbol values for atoms
- services get IDs, inheritance, versions, per-service renames, and
  protocol declarations; servers get names, auth, and protocol versions
- OpBindings.HTTP becomes a slice (gRPC transcoding additional_bindings)
- Property gains Presence (protobuf tri-state), ClientOptional/DefaultAdded
  (Smithy evolution model), EventPayload; WireID becomes *int (0 is a legal
  ordinal in Cap'n Proto/FlatBuffers/Avro)
- Visibility.None (@invisible), type-level XML/wire-name/media-type hints,
  richer Example (input/output/error scenarios, header+payload pairs),
  Availability on enum members/variants/params with add/remove cycles and
  optionality flips
- AuthKind covers the SASL/X509/userPassword families; Extensions and
  Provenance land on every node that can carry source metadata

The capability matrix gains an Erlang/OTP column, six new capability rows,
and ~25 cell corrections; lowering summaries are rewritten per format and
documented conventions added for degraded constructs (never-typed members,
bit-sized binaries, waiters, endpoint rules, GraphQL directive ordering).
The original prior-art survey of oagen was written from a high-level study;
auditing the actual source (parser, engine, and the differ/compat/verify
subsystems the survey never covered) verified every §1 claim, sharpened four
that were imprecise, and surfaced new lessons. None require IR schema
changes — the strongest result is negative: nothing in oagen's ~25k-line
codebase needed information the IR lacks, while its compat stack repeatedly
re-derives by heuristic (field-set matching, Jaccard overlay correlation)
the stable spec-level identity the IR carries by design.

- prior-art.md §1: verified/sharpened mistake rows (discriminated request
  bodies are also flattened; discriminator inference is structural but
  welded to derived names; unwrapping applied destructively), new rows
  (ref-kind-on-reference forcing global state, collision-cascade renames,
  name-list accretion), new worth-adopting entries (wire-identity-keyed
  hints, group-metadata-over-wire-list, generation manifests, spec-only
  smoke baselines, behavioral-change channel, narrow expiring approvals),
  and a new subsection on the diff/compat/verify subsystems
- architecture.md: real-world plan-layer decision list; canonical policy-
  input vocabulary with a declared-facts-win precedence rule; named
  write/integrate and surface-verification stages; filter-vs-scoped-
  regeneration distinction; pre-IR document patching vs IR overlay vs
  backend overlays; allowlist shape; wire-conformance test bullet
- ir-design.md: $ref-sibling merge precedence and union-of-consts
  normalization placement in the OpenAPI lowering row; documented promotion
  path for mutually-exclusive parameter groups; open question 5 gains the
  structural third correlation tier
@OmarAlJarrah
OmarAlJarrah merged commit 540f02d into main Jul 19, 2026
@OmarAlJarrah
OmarAlJarrah deleted the docs/ir-full-capability-surface branch July 19, 2026 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant